package com.ruoyi.system.util;

import com.ruoyi.common.constant.Constants;
import com.ruoyi.system.util.file.FilesEx;
import com.ruoyi.system.util.image.ImageHandler;
import com.ruoyi.system.util.image.Images;
import com.ruoyi.system.util.image.ScaleParam;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

@Service
public class UploadHandler {
    @Autowired
    private GlobalProperties getProperty;
    @Autowired
    private PathResolver pathResolver;

    protected final Logger logger = LoggerFactory.getLogger(UploadHandler.class);

    public void upload(String url, String type, Integer userId, String ip, UploadResult result) {
        upload(url, type, userId, ip, result, null, null, null, null, null, null, null, null);
    }

    public void upload(MultipartFile partFile, String type, Integer userId, String ip, UploadResult result) {
        upload(partFile, type, userId, ip, result, null, null, null, null, null, null, null, null);
    }

    public void upload(String url, String type, Integer userId, String ip, UploadResult result,
                       Boolean scale, Boolean exact, Integer width, Integer height, Boolean thumbnail, Integer thumbnailWidth,
                       Integer thumbnailHeight, Boolean watermark) {
        try {
            URL source = new URL(url);
            // file（下载）支持重定向支持，其他的不支持。
            if (Uploader.FILE.equals(type)) {
                HttpURLConnection.setFollowRedirects(true);
            } else {
                HttpURLConnection.setFollowRedirects(false);
            }
            HttpURLConnection conn = (HttpURLConnection) source.openConnection();
            conn.setRequestProperty("User-Agent", Constants.USER_ANGENT);
            int responseCode = conn.getResponseCode();
            if (responseCode != 200) {
                result.setError("URL response error:" + responseCode);
                return;
            }
            if (Uploader.IMAGE.equals(type)) {
                String contentType = conn.getContentType();
                if (!validateImageContentType(contentType, result)) {
                    return;
                }
            }
            String disposition = conn.getHeaderField(HttpHeaders.CONTENT_DISPOSITION);
            String fileName = StringUtils.substringBetween(disposition, "filename=\"", "\"");
            if (StringUtils.isBlank(fileName)) {
                fileName = FilenameUtils.getName(source.getPath());
            }
            String ext = FilenameUtils.getExtension(fileName);
            File temp = FilesEx.getTempFile(ext);
            InputStream is = conn.getInputStream();
            try {
                FileUtils.copyInputStreamToFile(is, temp);
                doUpload(temp, fileName, type, userId, ip, result, scale, exact, width, height, thumbnail,
                        thumbnailWidth, thumbnailHeight, watermark);
            } finally {
                IOUtils.closeQuietly(is);
                FileUtils.deleteQuietly(temp);
            }
        } catch (Exception e) {
            result.setError(e.getMessage());
        }
        return;
    }

    public void upload(MultipartFile partFile, String type, Integer userId, String ip, UploadResult result,
                       Boolean scale, Boolean exact, Integer width, Integer height, Boolean thumbnail, Integer thumbnailWidth,
                       Integer thumbnailHeight, Boolean watermark) {
        try {
            if (!validateFile(partFile, result)) {
                return;
            }
            String fileName = partFile.getOriginalFilename();
            String ext = FilenameUtils.getExtension(fileName);
            File temp = FilesEx.getTempFile(ext);
            partFile.transferTo(temp);
            try {
                doUpload(temp, fileName, type, userId, ip, result, scale, exact, width, height, thumbnail,
                        thumbnailWidth, thumbnailHeight, watermark);
            } finally {
                FileUtils.deleteQuietly(temp);
            }
        } catch (Exception e) {
            result.setError(e.getMessage());
            logger.error(null, e);
        }
        return;
    }

    private UploadResult doUpload(File file, String fileName, String type, Integer userId, String ip,
                                  UploadResult result, Boolean scale, Boolean exact, Integer width, Integer height, Boolean thumbnail,
                                  Integer thumbnailWidth, Integer thumbnailHeight, Boolean watermark) throws Exception {
        long fileLength = file.length();
        String ext = FilenameUtils.getExtension(fileName).toLowerCase();
        GlobalUpload gu = new GlobalUpload();//customes
        // 后缀名是否合法
        if (!validateExt(ext, type, gu, result)) {
            return result;
        }
        String urlPrefix = getProperty.getEnv().getProperty("ruoyi.profile");
        String pathname = Uploader.getQuickPathname(type, ext);
        String fileUrl = urlPrefix.substring(0, urlPrefix.length() - 1) + pathname;
        String pdfUrl = null;
        String swfUrl = null;
        if (Uploader.IMAGE.equals(type)) {
            doUploadImage(file, pathname, scale, exact, width, height, gu, ip, userId);
        }
        result.set(fileUrl, fileName, ext, fileLength, pdfUrl, swfUrl);
        return result;
    }

    private void doUploadImage(File file, String pathname, Boolean scale, Boolean exact,
                               Integer width, Integer height, GlobalUpload gu, String ip, Integer userId)
            throws IOException {
        ScaleParam scaleParam = gu.getScaleParam(scale, exact, width, height);

        String formatName = Images.getFormatName(file);

        if (StringUtils.isNotBlank(formatName)) {
            // 可以且需要处理的图片
//            storeImage(file, scaleParam, formatName, pathname, ip, userId);
            FileHandler.getLocalFileHandler(pathResolver, getProperty.getEnv().getProperty("ruoyi.profile")).storeFile(file, pathname);
        } else {
            // 不可处理的图片
            FileHandler.getLocalFileHandler(pathResolver, getProperty.getEnv().getProperty("ruoyi.profile")).storeFile(file, pathname);
        }
    }

    private void storeImage(File src, ScaleParam scaleParam,
                            String formatName, String pathname, String ip,
                            Integer userId) throws IOException {
        String srcPath = src.getAbsolutePath();
        if (scaleParam.isScale()) {
            imageHandler.resize(srcPath, srcPath, scaleParam);
        }

        boolean isThumbnail = false;
        Integer thumbnailWidth = 200;
        Integer thumbnailHeight = 200;
        if (isThumbnail) {
            File thumbnailFile = FilesEx.getTempFile();
            String thumbnailPath = thumbnailFile.getAbsolutePath();
            String thumbnailName = Uploader.getThumbnailName(pathname);
            FileHandler.getLocalFileHandler(pathResolver, getProperty.getEnv().getProperty("ruoyi.profile")).storeFile(thumbnailFile, thumbnailName);

            if (imageHandler.resize(srcPath, thumbnailPath, thumbnailWidth, thumbnailHeight, false)) {
                try {

                    FileHandler.getLocalFileHandler(pathResolver, getProperty.getEnv().getProperty("ruoyi.profile")).storeFile(thumbnailFile, thumbnailName);
                    // 新产生的缩略图要单独保存到附件，原图在doUpload里面保存到附件
                } finally {
                    // 确保删除临时文件
                    FileUtils.deleteQuietly(thumbnailFile);
                }
            }
        }

    }

    private boolean validateExt(String extension, String type, GlobalUpload gu, UploadResult result) {
        if (!gu.isExtensionValid(extension, type)) {
            logger.debug("image extension not allowed: " + extension);
            result.setErrorCode("imageExtensionNotAllowed", new String[]{extension});
            return false;
        }
        return true;
    }


    private boolean validateFile(MultipartFile partFile, UploadResult result) {
        if (partFile == null || partFile.isEmpty()) {
            logger.debug("file is empty");
            result.setError("no file upload!");
            return false;
        }
        return true;
    }

    private boolean validateImageContentType(String contentType, UploadResult result) {
        if (!StringUtils.contains(contentType, "image")) {
            logger.debug("ContentType not contain Image: " + contentType);
            result.setError("ContentType not contain Image: " + contentType);
            return false;
        }
        return true;
    }

    @Autowired
    protected ImageHandler imageHandler;

}
